import math,pickle

class Bayesian_Classifier(object):

    def mean_variance(self, list_values):
	"""calculate the mean and variance of each list of features"""
        sum = 0
        diff = 0
        d = {}
        for value in list_values:
            sum += value
        mean = float(sum)/len(list_values)
        for value in list_values:
            diff += (value-mean)**2
        variance = float(diff)/len(list_values)
        std_deviation = math.sqrt(variance)
        d["mean"] = mean
        d["std_deviation"] = std_deviation
        
        return d

    def calc_mean_variance(self, type):
	"""The method that calls mean_variance to find mean and deviation, and dumps the learning to another dictionary"""
	gauss_dist = {}
	if type == "safe":
	    l = pickle.load(open("log/safe_list.pkl",'rb'))
	    fout = open("log/safe_gauss_try.pkl",'wb')
	if type == "mal":
	    l = pickle.load(open("log/mal_list1.pkl",'rb'))
	    fout = open("log/mal_gauss_try1.pkl",'wb')
        gauss_dist["__avg_arg_len"]   = self.mean_variance(l["f1"])
        gauss_dist["__def_use"]       = self.mean_variance(l["f2"])
        gauss_dist["__per_readable"]  = self.mean_variance(l["f3"])  
        gauss_dist["__dynamic_calls"] = self.mean_variance(l["f4"])
        gauss_dist["__redirect"]      = self.mean_variance(l["f5"])
	gauss_dist["__hidden_iframe"] = self.mean_variance(l["f6"])
	gauss_dist["__activex"]       = self.mean_variance(l["f7"]) 

	pickle.dump(gauss_dist,fout,2)
	
    def estimate_prob(self, f_value, mean, deviation):
	"""gaussian model implementation, hidden called from classify"""
	exp_power = float((f_value - mean)**2)/(2*(deviation**2))
	prob = 1/(math.sqrt(2*math.pi)*deviation)*math.exp(-exp_power)
	return prob

    def gauss_dist(self,reader,type = "safe"):
	"""stores the extracted features per web page, dumps as a dictionary of list"""
	D = {}	
	if type == "safe":
	    fin = "log/safe_list.pkl"
	else:
	    fin = "log/mal_list1.pkl"		# this was done to store the malicious feature set in file other than mal_list.pkl
	try:
	    D = pickle.load(open(fin,'rb'))
	except:
	    if not D:
	        D = {"f1":[],"f2":[],"f3":[],"f4":[],"f5":[],"f6":[],"f7":[]}
	        
	
 	for k,v in reader.items():
	    if k == "__avg_arg_len":
	        D["f1"].append(v)
	    if k == "__def_use":
	        D["f2"].append(v)
	    if k == "__per_readable":
	        D["f3"].append(v)
	    if k == "__dynamic_calls":
		D["f4"].append(v)
	    if k == "__redirect":
		D["f5"].append(v)
	    if k == "__hidden_iframe":
		D["f6"].append(v)
	    if k == "__activex":
		D["f7"].append(v)
	
	pickle.dump(D,open(fin,'wb'),2)
	self.calc_mean_variance(type)

	
    def prior_prob(self):
	"""calculate the prior probability"""
	D = pickle.load(open("log/mal_list.pkl",'rb'))
	d = pickle.load(open("log/safe_list.pkl",'rb'))
	t_mal = len(D["f1"])
	t_safe = len(d["f1"])
	self.__dict__["safe_pr_prob"] = float(t_safe)/(t_safe+t_mal)
	self.__dict__["mal_pr_prob"] = float(t_mal)/(t_safe+t_mal)

    def classify_script(self,features):
	"""classify the features of a script into either mal or safe based on the learning"""
	for k,v in features.items():  
		if k == "__avg_arg_len":
		    p1_m = self.mal_gauss_prob("__avg_arg_len",v)
		    p1_s = self.safe_gauss_prob("__avg_arg_len",v)
		if k == "__def_use":
	    	    p2_m = self.mal_gauss_prob("__def_use",v)
	    	    p2_s = self.safe_gauss_prob("__def_use",v)
		if k == "__per_readable":
		    p3_m = self.mal_gauss_prob("__per_readable",v)
		    p3_s = self.safe_gauss_prob("__per_readable",v)
		if k == "__dynamic_calls":
		    p4_m = self.mal_gauss_prob("__dynamic_calls",v)
		    p4_s = self.safe_gauss_prob("__dynamic_calls",v)
		if k == "__redirect":
		    p5_m = self.mal_gauss_prob("__redirect",v)
		    p5_s = self.safe_gauss_prob("__redirect",v)
		if k == "__hidden_iframe":
		    p6_m = self.mal_gauss_prob("__hidden_iframe",v)
		    p6_s = self.safe_gauss_prob("__hidden_iframe",v)
		if k == "__activex":
		    p7_m = self.mal_gauss_prob("__activex",v)
		    p7_s = self.safe_gauss_prob("__activex",v)

        self.__dict__["post_prob_mal"] = p1_m*p2_m*p3_m*p4_m*p5_m*p6_m*p7_m
	self.__dict__["post_prob_safe"] = p1_s*p2_s*p3_s*p4_s*p5_s*p6_s*p7_s

	self.prior_prob()

	p_mal,p_safe = self.classify()
	return p_mal,p_safe

    def mal_gauss_prob(self,fvalue,v):
	"""posterior probability for malicious learned samples"""
	fin = open("log/mal_gauss_try.pkl",'rb')
	mal = pickle.load(fin)
	post_prob_mal = 0.0

	for k in mal.keys():
	    if k == fvalue:
		d = mal[k]
		post_prob_mal = self.estimate_prob(v,d["mean"],d["std_deviation"])

	return post_prob_mal

    def safe_gauss_prob(self,fvalue,v):
	fin = open("log/safe_gauss_try.pkl",'rb')
	safe = pickle.load(fin)
	post_prob_safe = 0.0

	for k in safe.keys():
	    if k == fvalue:
		d = safe[k]
		post_prob_safe = self.estimate_prob(v,d["mean"],d["std_deviation"])

	return post_prob_safe


    def classify(self):
	"""visible method places call to posterior probability methods of both mal and safe type"""
	p_safe = self.__dict__["post_prob_safe"]*self.__dict__["safe_pr_prob"]
	p_mal = self.__dict__["post_prob_mal"]*self.__dict__["mal_pr_prob"]
	return p_mal, p_safe

#	if p_mal > p_safe: print "malicious"
#	else: print "safe"
